<?php

namespace app\controllers;

use app\redis\api\Attack;
use app\redis\api\RunLong;
use app\util\Util;
use wsl\ip2location\Ip2Location;
use Yii;
use yii\web\Response;

/**
 * Base Controller
 *
 * Class Controller
 * @package app\controllers
 */
abstract class Controller extends \yii\web\Controller
{
    /*
     * api request time
     */
    protected $startTime    = 0;
    protected $endTime      = 0;

    /*
     * api request url
     */
    public $action       = null;

    public $config;

    public function beforeAction($action)
    {
        /**
         * save start time
         * save api url
         */
        $this->startTime = microtime(true);
        $this->action = $action->getUniqueId();

        // config
        $this->config = require __DIR__ . '/config.php';

        return true;
    }

    /**
     * response json
     *
     * @param null $data
     * @param null $message
     * @param null $code
     * @return \yii\web\Response
     */
    public function json($data = null, $message = null, $code = null)
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $this->endTime = microtime(true);
        $runTime = round($this->endTime - $this->startTime, 3);

        /**
         * Save run long logs
         * > 1s
         */
        if ($runTime > 1) {
            $runLong = new RunLong();
            $runLong->api = $this->action;
            // $runLong->ip = \Yii::$app->request->userIP;
            $runLong->ip = Util::getClientIp();
            $runLong->run_time = $runTime;
            $runLong->create_time = date('Y-m-d H:i:s');

            // ip to address
            $ipLocation = new Ip2Location();
            $address = $ipLocation->getLocation($runLong->ip);
            $runLong->country = $address['country'];
            $runLong->area = $address['area'];

            $runLong->save();
        }

        $result['unique']   = uniqid();
        $result['runTime']  = $runTime;
        $result['code']     = intval($code);
        $result['data']     = $data;
        $result['message']  = $message;

        /**
         * prevent attacks
         *  request ip & api
         */
        if ($this->config['attack']) {
            // $ip = \Yii::$app->request->userIP;
            $ip = Util::getClientIp();
            $api  = $this->action;
            $attack = new Attack();
            $attack->ip = $ip;
            $attack->api = $api;
            $attack->timestamp = time();
            $attack->save();

            if (Attack::isAttack($ip, $api)) {
                return ['kill' => '!!!'];
            }
        }

        return $result;
    }

    /**
     * success response
     *
     * @param array $data
     * @param string $message
     * @return \yii\web\Response
     */
    public function success($data = [], $message = '操作成功')
    {
        $code = Yii::$app->params['CODE_SUCCESS'];
        return $this->json($data, $message, $code);
    }

    /**
     * fail response
     *
     * @param string $message
     * @param null $code
     * @return \yii\web\Response
     */
    public function fail($message = '操作失败', $code = null)
    {
        if (!$code) {
            $code = Yii::$app->params['CODE_ERROR'];
        }

        return $this->json(null, $message, $code);
    }

    public function customFail($message = '错误')
    {
        $code = Yii::$app->params['CODE_ERROR_CUSTOM'];

        return $this->fail($message, $code);
    }

    /**
     * nothing
     *
     * @param string $message
     * @return array|string[]|Response
     */
    public function nothing($message = 'nothing')
    {
        $code = Yii::$app->params['CODE_NOTHING'];

        return $this->json(null, $message, $code);
    }

    protected function get($name = null, $defaultValue = null)
    {
        return Yii::$app->request->get($name, $defaultValue);
    }

    protected function post($name = null, $defaultValue = null)
    {
        return Yii::$app->request->post($name, $defaultValue);
    }

    protected function encode($data = [])
    {
        if (is_array($data)) {
            $data = json_encode($data);
        }

        $m1 = base64_encode(Yii::$app->params['JSON_KEY1'] . $data);
        $m2 = base64_encode(Yii::$app->params['JSON_KEY2'] . $m1);

        return Yii::$app->params['JSON_AA'] . $m2;
    }

    protected function successEncode($data = [], $message = '操作成功')
    {
        $data = $this->encode($data);

        return $this->success($data, $message);
    }
}